<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>JavaScript类(Class)完全指南 | 时间领主的博客</title>
    <meta name="generator" content="VuePress 1.4.1">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@babel/standalone/babel.min.js"></script>
    <link rel="icon" href="/blog/favicon.ico">
    <meta name="description" content="行动不一定带来快乐，而无行动则决无快乐">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
    <link rel="preload" href="/blog/assets/css/0.styles.174d23e9.css" as="style"><link rel="preload" href="/blog/assets/js/app.c6f0b635.js" as="script"><link rel="preload" href="/blog/assets/js/3.56d0db2f.js" as="script"><link rel="preload" href="/blog/assets/js/1.dc177a2a.js" as="script"><link rel="preload" href="/blog/assets/js/18.b7c7c6f0.js" as="script"><link rel="prefetch" href="/blog/assets/js/10.3ea1e65e.js"><link rel="prefetch" href="/blog/assets/js/11.b138a709.js"><link rel="prefetch" href="/blog/assets/js/12.98d3dec7.js"><link rel="prefetch" href="/blog/assets/js/13.1a8500fb.js"><link rel="prefetch" href="/blog/assets/js/14.d52be3d5.js"><link rel="prefetch" href="/blog/assets/js/15.e6ebcc21.js"><link rel="prefetch" href="/blog/assets/js/16.515c742f.js"><link rel="prefetch" href="/blog/assets/js/17.8ebf8e60.js"><link rel="prefetch" href="/blog/assets/js/19.0ccdcb93.js"><link rel="prefetch" href="/blog/assets/js/20.78e9f5a5.js"><link rel="prefetch" href="/blog/assets/js/21.5e84bd81.js"><link rel="prefetch" href="/blog/assets/js/22.eff4bf70.js"><link rel="prefetch" href="/blog/assets/js/23.1417d381.js"><link rel="prefetch" href="/blog/assets/js/24.013e4313.js"><link rel="prefetch" href="/blog/assets/js/25.f3067eb6.js"><link rel="prefetch" href="/blog/assets/js/26.19fe9c6d.js"><link rel="prefetch" href="/blog/assets/js/27.c089c5d4.js"><link rel="prefetch" href="/blog/assets/js/28.6ff3368c.js"><link rel="prefetch" href="/blog/assets/js/29.d1cc7d1f.js"><link rel="prefetch" href="/blog/assets/js/30.0dc56898.js"><link rel="prefetch" href="/blog/assets/js/31.b5bac1d5.js"><link rel="prefetch" href="/blog/assets/js/32.fbc30039.js"><link rel="prefetch" href="/blog/assets/js/33.7070e81d.js"><link rel="prefetch" href="/blog/assets/js/34.e7c86927.js"><link rel="prefetch" href="/blog/assets/js/35.c731e557.js"><link rel="prefetch" href="/blog/assets/js/36.151c6972.js"><link rel="prefetch" href="/blog/assets/js/37.019d3b29.js"><link rel="prefetch" href="/blog/assets/js/4.6a4255d5.js"><link rel="prefetch" href="/blog/assets/js/5.829faed3.js"><link rel="prefetch" href="/blog/assets/js/6.b91d75cb.js"><link rel="prefetch" href="/blog/assets/js/7.7aafbc48.js"><link rel="prefetch" href="/blog/assets/js/8.982bf0b3.js"><link rel="prefetch" href="/blog/assets/js/9.283b0ce1.js">
    <link rel="stylesheet" href="/blog/assets/css/0.styles.174d23e9.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div><div class="theme-container" data-v-4698c43e><div data-v-4698c43e><div id="loader-wrapper" class="loading-wrapper" data-v-4b73742e data-v-4698c43e data-v-4698c43e><div class="loader-main" data-v-4b73742e><div data-v-4b73742e></div><div data-v-4b73742e></div><div data-v-4b73742e></div><div data-v-4b73742e></div></div> <!----> <!----></div> <div class="password-shadow password-wrapper-out" style="display:none;" data-v-6cbeab0a data-v-4698c43e data-v-4698c43e><h3 class="title" style="display:none;" data-v-6cbeab0a data-v-6cbeab0a>时间领主的博客</h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-6cbeab0a data-v-6cbeab0a><input type="password" value="" data-v-6cbeab0a> <span data-v-6cbeab0a>Konck! Knock!</span> <button data-v-6cbeab0a>OK</button></label> <div class="footer" style="display:none;" data-v-6cbeab0a data-v-6cbeab0a><span data-v-6cbeab0a><i class="iconfont reco-theme" data-v-6cbeab0a></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-6cbeab0a>vuePress-theme-reco</a></span> <span data-v-6cbeab0a><i class="iconfont reco-copyright" data-v-6cbeab0a></i> <a data-v-6cbeab0a><span data-v-6cbeab0a>时间领主</span>
            
          <span data-v-6cbeab0a>2019 - </span>
          2020
        </a></span></div></div> <div class="hide" data-v-4698c43e><header class="navbar" data-v-4698c43e><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/blog/" class="home-link router-link-active"><!----> <span class="site-name">时间领主的博客</span></a> <div class="links"><div class="color-picker"><a class="color-button"><i class="iconfont reco-color"></i></a> <div class="color-picker-menu" style="display:none;"><div class="mode-options"><h4 class="title">Choose mode</h4> <ul class="color-mode-options"><li class="dark">dark</li><li class="auto active">auto</li><li class="light">light</li></ul></div></div></div> <div class="search-box"><i class="iconfont reco-search"></i> <input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/blog/" class="nav-link"><i class="iconfont reco-home"></i>
  首页
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-category"></i>
      分类
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/categories/前端/" class="nav-link"><i class="iconfont undefined"></i>
  前端
</a></li><li class="dropdown-item"><!----> <a href="/blog/categories/Light-UI 组件库/" class="nav-link"><i class="iconfont undefined"></i>
  Light-UI 组件库
</a></li><li class="dropdown-item"><!----> <a href="/blog/categories/数据库/" class="nav-link"><i class="iconfont undefined"></i>
  数据库
</a></li><li class="dropdown-item"><!----> <a href="/blog/categories/问题/" class="nav-link"><i class="iconfont undefined"></i>
  问题
</a></li><li class="dropdown-item"><!----> <a href="/blog/categories/面试/" class="nav-link"><i class="iconfont undefined"></i>
  面试
</a></li></ul></div></div><div class="nav-item"><a href="/blog/tag/" class="nav-link"><i class="iconfont reco-tag"></i>
  标签
</a></div><div class="nav-item"><a href="https://gitee.com/caohuiboss" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont undefined"></i>
  码云
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="nav-item"><a href="https://cn.bing.com/" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont undefined"></i>
  必应
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav></div></header> <div class="sidebar-mask" data-v-4698c43e></div> <aside class="sidebar" data-v-4698c43e><div class="personal-info-wrapper" data-v-6c8ffc9c><img src="/blog/avatar.gif" alt="author-avatar" class="personal-img" data-v-6c8ffc9c> <h3 class="name" data-v-6c8ffc9c>
    时间领主
  </h3> <div class="num" data-v-6c8ffc9c><div data-v-6c8ffc9c><h3 data-v-6c8ffc9c>26</h3> <h6 data-v-6c8ffc9c>文章</h6></div> <div data-v-6c8ffc9c><h3 data-v-6c8ffc9c>8</h3> <h6 data-v-6c8ffc9c>标签</h6></div></div> <hr data-v-6c8ffc9c></div> <nav class="nav-links"><div class="nav-item"><a href="/blog/" class="nav-link"><i class="iconfont reco-home"></i>
  首页
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-category"></i>
      分类
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/categories/前端/" class="nav-link"><i class="iconfont undefined"></i>
  前端
</a></li><li class="dropdown-item"><!----> <a href="/blog/categories/Light-UI 组件库/" class="nav-link"><i class="iconfont undefined"></i>
  Light-UI 组件库
</a></li><li class="dropdown-item"><!----> <a href="/blog/categories/数据库/" class="nav-link"><i class="iconfont undefined"></i>
  数据库
</a></li><li class="dropdown-item"><!----> <a href="/blog/categories/问题/" class="nav-link"><i class="iconfont undefined"></i>
  问题
</a></li><li class="dropdown-item"><!----> <a href="/blog/categories/面试/" class="nav-link"><i class="iconfont undefined"></i>
  面试
</a></li></ul></div></div><div class="nav-item"><a href="/blog/tag/" class="nav-link"><i class="iconfont reco-tag"></i>
  标签
</a></div><div class="nav-item"><a href="https://gitee.com/caohuiboss" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont undefined"></i>
  码云
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="nav-item"><a href="https://cn.bing.com/" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont undefined"></i>
  必应
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>JavaScript类(Class)完全指南</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/blog/views/JavaScript/JavaScript%E7%B1%BB(Class)%E5%AE%8C%E5%85%A8%E6%8C%87%E5%8D%97.html#_1-定义-类关键字" class="sidebar-link">1. 定义:类关键字</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/blog/views/JavaScript/JavaScript%E7%B1%BB(Class)%E5%AE%8C%E5%85%A8%E6%8C%87%E5%8D%97.html#_2-初始化-constructor" class="sidebar-link">2. 初始化:constructor()</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/blog/views/JavaScript/JavaScript%E7%B1%BB(Class)%E5%AE%8C%E5%85%A8%E6%8C%87%E5%8D%97.html#_3-字段" class="sidebar-link">3.字段</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/blog/views/JavaScript/JavaScript%E7%B1%BB(Class)%E5%AE%8C%E5%85%A8%E6%8C%87%E5%8D%97.html#_4-方法" class="sidebar-link">4.方法</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/blog/views/JavaScript/JavaScript%E7%B1%BB(Class)%E5%AE%8C%E5%85%A8%E6%8C%87%E5%8D%97.html#_5-继承-extends" class="sidebar-link">5. 继承: extends</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/blog/views/JavaScript/JavaScript%E7%B1%BB(Class)%E5%AE%8C%E5%85%A8%E6%8C%87%E5%8D%97.html#_6-对象类型检查：instanceof" class="sidebar-link">6.对象类型检查：instanceof</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/blog/views/JavaScript/JavaScript%E7%B1%BB(Class)%E5%AE%8C%E5%85%A8%E6%8C%87%E5%8D%97.html#_7-类和原型" class="sidebar-link">7. 类和原型</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <div class="password-shadow password-wrapper-in" style="display:none;" data-v-6cbeab0a data-v-4698c43e><h3 class="title" style="display:none;" data-v-6cbeab0a data-v-6cbeab0a>JavaScript类(Class)完全指南</h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-6cbeab0a data-v-6cbeab0a><input type="password" value="" data-v-6cbeab0a> <span data-v-6cbeab0a>Konck! Knock!</span> <button data-v-6cbeab0a>OK</button></label> <div class="footer" style="display:none;" data-v-6cbeab0a data-v-6cbeab0a><span data-v-6cbeab0a><i class="iconfont reco-theme" data-v-6cbeab0a></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-6cbeab0a>vuePress-theme-reco</a></span> <span data-v-6cbeab0a><i class="iconfont reco-copyright" data-v-6cbeab0a></i> <a data-v-6cbeab0a><span data-v-6cbeab0a>时间领主</span>
            
          <span data-v-6cbeab0a>2019 - </span>
          2020
        </a></span></div></div> <div data-v-4698c43e><main class="page"><!----> <div class="page-title" style="display:none;"><h1>JavaScript类(Class)完全指南</h1> <hr> <div data-v-484a899e><i class="iconfont reco-account" data-v-484a899e><span data-v-484a899e>时间领主</span></i> <i class="iconfont reco-date" data-v-484a899e><span data-v-484a899e>2019-08-01</span></i> <!----> <i class="iconfont reco-tag tags" data-v-484a899e><span class="tag-item" data-v-484a899e>
      JavaScript
    </span></i></div></div> <div class="content__default"><h1 id="javascript类-class-完全指南"><a href="#javascript类-class-完全指南" class="header-anchor">#</a> JavaScript类(Class)完全指南</h1> <blockquote><p>JavaScript 使用原型继承:每个对象都从原型对象继承属性和方法。
在Java或Swift等语言中使用的传统类作为创建对象的蓝图，在 JavaScript 中不存在，原型继承仅处理对象。
原型继承可以模拟经典类继承。为了将传统的类引入 JavaScript, ES2015 标准引入了class语法，其底层实现还是基于原型，只是原型继承的语法糖。
本文章主要让我熟悉 JavaScript 类:如何定义类，初始化实例，定义字段和方法，理解私有和公共字段，掌握静态字段和方法。</p></blockquote> <h2 id="_1-定义-类关键字"><a href="#_1-定义-类关键字" class="header-anchor">#</a> 1. 定义:类关键字</h2> <p>使用关键字class可以在 JS 中定义了一个类：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    // 类的主体
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>上面的代码定义了一个User类。 大括号{}里面是类的主体。 此语法称为class 声明。</p> <p>如果在定义类时没有指定类名。可以通过使用类表达式，将类分配给变量：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>const UserClass = class {
    // 类的主体
};
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>还可以轻松地将类导出为 ES6 模块的一部分，默认导出语法如下：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>export default class User {
    // 主体
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>命名导出如下：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>export class User {
    // 主体
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>当我们创建类的实例时，该类将变得非常有用。实例是包含类所描述的数据和行为的对象。</p> <p>使用new运算符实例化该类，语法：instance = new Class()。</p> <p>例如，可以使用new操作符实例化User类：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>const myUser = new User();
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h2 id="_2-初始化-constructor"><a href="#_2-初始化-constructor" class="header-anchor">#</a> 2. 初始化:constructor()</h2> <p>constructor(param1, param2, ...)是用于初始化实例的类主体中的一种特殊方法。 在这里可以设置字段的初始值或进行任何类型的对象设置。</p> <p>在下面的示例中，构造函数设置字段name的初始值</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    constructor(name) {
        this.name = name;
    }
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>User的构造函数有一个参数 name，用于设置字段this.name的初始值</p> <p>在构造函数中，this 值等于新创建的实例。用于实例化类的参数成为构造函数的参数：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    constructor(name) {
        name; // =&gt; 'Fundebug'
        this.name = name;
    }
}

const user = new User(&quot;Fundebug&quot;);
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>构造函数中的name参数的值为'Fundebug'。如果没有定义该类的构造函数，则会创建一个默认的构造函数。默认的构造函数是一个空函数，它不修改实例。</p> <p>同时，一个 JavaScript 类最多可以有一个构造函数。</p> <h2 id="_3-字段"><a href="#_3-字段" class="header-anchor">#</a> 3.字段</h2> <p>类字段是保存信息的变量，字段可以附加到两个实体：</p> <ol><li><p>类实例上的字段</p></li> <li><p>类本身的字段(也称为静态字段)
字段有两种级别可访问性：</p></li> <li><p>public:该字段可以在任何地方访问</p></li> <li><p>private:字段只能在类的主体中访问</p></li></ol> <p><strong>3.1 公共实例字段</strong></p> <p>让我们再次看看前面的代码片段:</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    constructor(name) {
        this.name = name;
    }
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>表达式this.name = name创建一个实例字段名，并为其分配一个初始值。然后，可以使用属性访问器访问name字段</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>const user = new User(&quot;Fundebug&quot;);
user.name; // =&gt; 'Fundebug'
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>name是一个公共字段，因为你可以在User类主体之外访问它。</p> <p>当字段在构造函数中隐式创建时，就像前面的场景一样，可能获取所有字段。必须从构造函数的代码中破译它们。</p> <p>class fields proposal 提案允许我们在类的主体中定义字段，并且可以立即指定初始值：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class SomeClass {
    field1;
    field2 = &quot;Initial value&quot;;

    // ...
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>接着我们修改User类并声明一个公共字段name：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    name;

    constructor(name) {
        this.name = name;
    }
}

const user = new User(&quot;Fundebug&quot;);
user.name; // =&gt; 'Fundebug'
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>name;在类的主体中声明一个公共字段name。</p> <p>以这种方式声明的公共字段具有表现力：快速查看字段声明就足以了解类的数据结构，而且，类字段可以在声明时立即初始化。</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    name = &quot;无名氏&quot;;

    constructor() {}
}

const user = new User();
user.name; // '无名氏'
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>类体内的name ='无名氏'声明一个字段名称，并使用值'无名氏'对其进行初始化。</p> <p>对公共字段的访问或更新没有限制。可以读取构造函数、方法和类外部的公共字段并将其赋值。</p> <p><strong>3.2 私有实例字段</strong></p> <p>封装是一个重要的概念，它允许我们隐藏类的内部细节。使用封装类只依赖类提供的公共接口，而不耦合类的实现细节。</p> <p>当实现细节改变时，考虑到封装而组织的类更容易更新。</p> <p>隐藏对象内部数据的一种好方法是使用私有字段。这些字段只能在它们所属的类中读取和更改。类的外部世界不能直接更改私有字段。</p> <p><em><strong>私有字段只能在类的主体中访问</strong></em></p> <p>在字段名前面加上特殊的符号#使其成为私有的，例如#myField。每次处理字段时都必须保留前缀#声明它、读取它或修改它。</p> <p>确保在实例初始化时可以一次设置字段#name：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
  #name;

  constructor (name) {
    this.#name = name;
  }

  getName() {
    return this.#name;
  }
}

const user = new User('Fundebug')
user.getName() // =&gt; 'Fundebug'

user.#name  // 抛出语法错误
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>#name是一个私有字段。可以在User内访问和修改#name。方法getName()可以访问私有字段#name。</p> <p>但是，如果我们试图在 User 主体之外访问私有字段#name，则会抛出一个语法错误:SyntaxError: Private field '#name' must be declared in an enclosing class。</p> <p><strong>3.3 公共静态字段</strong></p> <p>我们还可以在类本身上定义字段:静态字段。这有助于定义类常量或存储特定于该类的信息。</p> <p>要在 JavaScript 类中创建静态字段，请使用特殊的关键字static后面跟字段名:static myStaticField</p> <p>让我们添加一个表示用户类型的新字段type:admin或regular。静态字TYPE_ADMIN和TYPE_REGULAR是区分用户类型的常量:</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    static TYPE_ADMIN = &quot;admin&quot;;
    static TYPE_REGULAR = &quot;regular&quot;;

    name;
    type;

    constructor(name, type) {
        this.name = name;
        this.type = type;
    }
}

const admin = new User(&quot;Fundebug&quot;, User.TYPE_ADMIN);
admin.type === User.TYPE_ADMIN; // =&gt; true

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>static TYPE_ADMIN和static TYPE_REGULAR在User类内部定义了静态变量。 要访问静态字段，必须使用后跟字段名称的类：User.TYPE_ADMIN和User.TYPE_REGULAR。</p> <p><strong>3.4 私有静态字段</strong></p> <p>有时，我们也想隐藏静态字段的实现细节，在时候，就可以将静态字段设为私有。</p> <p>要使静态字段成为私有的，只要字段名前面加上#符号:static #myPrivateStaticField。</p> <p>假设我们希望限制User类的实例数量。要隐藏实例限制的详细信息，可以创建私有静态字段：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    static #MAX_INSTANCES = 2;
    static #instances = 0;

    name;

    constructor(name) {
        User.#instances++;
        if (User.#instances &gt; User.#MAX_INSTANCES) {
            throw new Error(&quot;Unable to create User instance&quot;);
        }
        this.name = name;
    }
}

new User(&quot;张三&quot;);
new User(&quot;李四&quot;);
new User(&quot;王五&quot;); // throws Error
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>静态字段User.#MAX_INSTANCES设置允许的最大实例数，而User.#instances静态字段则计算实际的实例数。</p> <p>这些私有静态字段只能在User类中访问，类的外部都不会干扰限制机制：这就是封装的好处。</p> <h2 id="_4-方法"><a href="#_4-方法" class="header-anchor">#</a> 4.方法</h2> <p>字段保存数据，但是修改数据的能力是由属于类的一部分的特殊功能实现的：方法。</p> <p><strong>4.1 实例方法</strong></p> <p>JavaScript 类同时支持实例和静态方法。
实例方法可以访问和修改实例数据。实例方法可以调用其他实例方法，也可以调用任何静态方法。</p> <p>例如，定义一个方法getName()，它返回User类中的name ：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    name = &quot;无名氏&quot;;

    constructor(name) {
        this.name = name;
    }

    getName() {
        return this.name;
    }
}

const user = new User(&quot;Fundebug&quot;);
user.getName(); // =&gt; 'Fundebug'

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p>getName() { ... }是User类中的一个方法，getname()是一个方法调用:它执行方法并返回计算值(如果存在的话)。</p> <p>在类方法和构造函数中，this值等于类实例。使用this来访问实例数据:this.field 或者调用其他方法:this.method()。</p> <p>接着我们添加一个具有一个参数并调用另一种方法的新方法名称nameContains(str)：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    name;

    constructor(name) {
        this.name = name;
    }

    getName() {
        return this.name;
    }

    nameContains(str) {
        return this.getName().includes(str);
    }
}

const user = new User(&quot;Fundebug&quot;);
user.nameContains(&quot;Fun&quot;); // =&gt; true
user.nameContains(&quot;code&quot;); // =&gt; false

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><p>nameContains(str) { ... }是User类的一种方法，它接受一个参数str。 不仅如此，它还执行实例this.getName()的方法来获取用户名。</p> <p>方法也可以是私有的。 为了使方法私有前缀，名称以＃开头即可，如下所示：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
  #name;

  constructor(name) {
    this.#name = name;
  }

  #getName() {
    return this.#name;
  }

  nameContains(str) {
    return this.#getName().includes(str);
  }
}

const user = new User('Fundebug');
user.nameContains('Fun');   // =&gt; true
user.nameContains('Code'); // =&gt; false

user.#getName(); // SyntaxError is thrown

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br></div></div><p>#getName()是一个私有方法。在方法nameContains(str)中，可以这样调用一个私有方法:this.#getName()。</p> <p>由于是私有的，#getName()不能在用User 类主体之外调用。</p> <p><strong>4.2 getters 和 setters</strong></p> <p>getter和setter模仿常规字段，但是对如何访问和更改字段具有更多控制。在尝试获取字段值时执行getter，而在尝试设置值时使用setter。</p> <p>为了确保User的name属性不能为空，我们将私有字段#nameValue封装在getter和setter中:</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    #nameValue;

    constructor(name) {
        this.name = name;
    }

    get name() {
        return this.#nameValue;
    }

    set name(name) {
        if (name === &quot;&quot;) {
            throw new Error(`name field of User cannot be empty`);
        }
        this.#nameValue = name;
    }
}

const user = new User(&quot;Fundebug&quot;);
user.name; // getter 被调用, =&gt; 'Fundebug'
user.name = &quot;Code&quot;; // setter 被调用

user.name = &quot;&quot;; // setter 抛出一个错误
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><p>get name() {...} 在访问user.name会被执行。而set name(name){…}在字段更新(user.name = 'Fundebug')时执行。如果新值是空字符串，setter将抛出错误。</p> <p><strong>4.3 静态方法</strong></p> <p>静态方法是直接附加到类的函数，它们持有与类相关的逻辑，而不是类的实例。</p> <p>要创建一个静态方法，请使用特殊的关键字static和一个常规的方法语法:static myStaticMethod() { ... }。</p> <p>使用静态方法时，有两个简单的规则需要记住：</p> <ol><li>静态方法可以访问静态字段。</li> <li>静态方法不能访问实例字段。
例如，创建一个静态方法来检测是否已经使用了具有特定名称的用户。</li></ol> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    static #takenNames = [];

    static isNameTaken(name) {
        return User.#takenNames.includes(name);
    }

    name = &quot;无名氏&quot;;

    constructor(name) {
        this.name = name;
        User.#takenNames.push(name);
    }
}

const user = new User(&quot;Fundebug&quot;);

User.isNameTaken(&quot;Fundebug&quot;); // =&gt; true
User.isNameTaken(&quot;Code&quot;); // =&gt; false
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br></div></div><p>isNameTaken()是一个使用静态私有字段User的静态方法用于检查已取的名字。</p> <p>静态方法可以是私有的:static #staticFunction() {...}。同样，它们遵循私有规则:只能在类主体中调用私有静态方法。</p> <h2 id="_5-继承-extends"><a href="#_5-继承-extends" class="header-anchor">#</a> 5. 继承: extends</h2> <p>JavaScript 中的类使用extends关键字支持单继承。
在class Child extends Parent { }表达式中，Child类从Parent继承构造函数，字段和方法。</p> <p>例如，我们创建一个新的子类ContentWriter来继承父类User。</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    name;

    constructor(name) {
        this.name = name;
    }

    getName() {
        return this.name;
    }
}

class ContentWriter extends User {
    posts = [];
}

const writer = new ContentWriter(&quot;John Smith&quot;);

writer.name; // =&gt; 'John Smith'
writer.getName(); // =&gt; 'John Smith'
writer.posts; // =&gt; []

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br></div></div><p>ContentWriter继承了User的构造函数，方法getName()和字段name。同样，ContentWriter类声明了一个新的字段posts。</p> <p><em><strong>注意，父类的私有成员不会被子类继承</strong></em></p> <p><strong>5.1 父构造函数：constructor()中的super()</strong></p> <p>如果希望在子类中调用父构造函数，则需要使用子构造函数中可用的super()特殊函数。</p> <p>例如，让ContentWriter构造函数调用User的父构造函数，以及初始化posts字段</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    name;

    constructor(name) {
        this.name = name;
    }

    getName() {
        return this.name;
    }
}

class ContentWriter extends User {
    posts = [];

    constructor(name, posts) {
        super(name);
        this.posts = posts;
    }
}

const writer = new ContentWriter(&quot;Fundebug&quot;, [&quot;Why I like JS&quot;]);
writer.name; // =&gt; 'Fundebug'
writer.posts; // =&gt; ['Why I like JS']
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><p>子类ContentWriter中的super(name)执行父类User的构造函数。</p> <p><em><strong>注意，在使用this关键字之前，必须在子构造函数中执行super()。调用super()确保父构造函数初始化实例。</strong></em></p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class Child extends Parent {
    constructor(value1, value2) {
        //无法工作
        this.prop2 = value2;
        super(value1);
    }
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p><strong>5.2 父实例:方法中的super</strong></p> <p>如果希望在子方法中访问父方法，可以使用特殊的快捷方式super。</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    name;

    constructor(name) {
        this.name = name;
    }

    getName() {
        return this.name;
    }
}

class ContentWriter extends User {
    posts = [];

    constructor(name, posts) {
        super(name);
        this.posts = posts;
    }

    getName() {
        const name = super.getName();
        if (name === &quot;&quot;) {
            return &quot;无名氏&quot;;
        }
        return name;
    }
}

const writer = new ContentWriter(&quot;Fundebug&quot;, [&quot;Why I like JS&quot;]);
writer.getName(); // =&gt; '无名氏'

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br></div></div><p>子类ContentWriter的getName()直接从父类User访问方法super.getName()，这个特性称为方法重写。</p> <p><em><strong>注意，也可以在静态方法中使用super来访问父类的静态方法。</strong></em></p> <h2 id="_6-对象类型检查：instanceof"><a href="#_6-对象类型检查：instanceof" class="header-anchor">#</a> 6.对象类型检查：instanceof</h2> <p>object instanceof Class是确定object 是否为Class实例的运算符，来看看示例：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    name;

    constructor(name) {
        this.name = name;
    }

    getName() {
        return this.name;
    }
}

const user = new User(&quot;Fundebug&quot;);
const obj = {};

user instanceof User; // =&gt; true
obj instanceof User; // =&gt; false

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>user是User类的一个实例，user instanceof User的计算结果为true。</p> <p>空对象{}不是User的实例，相应地obj instanceof User为false。</p> <p>instanceof是多态的:操作符检测作为父类实例的子类。</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    name;

    constructor(name) {
        this.name = name;
    }

    getName() {
        return this.name;
    }
}

class ContentWriter extends User {
    posts = [];

    constructor(name, posts) {
        super(name);
        this.posts = posts;
    }
}

const writer = new ContentWriter(&quot;Fundebug&quot;, [&quot;Why I like JS&quot;]);

writer instanceof ContentWriter; // =&gt; true
writer instanceof User; // =&gt; true
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><p>writer是子类ContentWriter的一个实例。运算符writer instanceof ContentWriter的计算结果为true。</p> <p>同时ContentWriter是User的子类。因此writer instanceof User结果也为true。</p> <p>如果想确定实例的确切类，该怎么办?可以使用构造函数属性并直接与类进行比较</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>writer.constructor === ContentWriter; // =&gt; true
writer.constructor === User; // =&gt; false
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h2 id="_7-类和原型"><a href="#_7-类和原型" class="header-anchor">#</a> 7. 类和原型</h2> <p>必须说 JS 中的类语法在从原型继承中抽象方面做得很好。但是，类是在原型继承的基础上构建的。每个类都是一个函数，并在作为构造函数调用时创建一个实例。</p> <p>以下两个代码段是等价的。</p> <p>类版本：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>class User {
    constructor(name) {
        this.name = name;
    }

    getName() {
        return this.name;
    }
}

const user = new User(&quot;Fundebug&quot;);

user.getName(); // =&gt; 'Fundebug'
user instanceof User; // =&gt; true
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p>使用原型的版本：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>function User(name) {
    this.name = name;
}

User.prototype.getName = function() {
    return this.name;
};

const user = new User(&quot;Fundebug&quot;);

user.getName(); // =&gt; 'Fundebug'
user instanceof User; // =&gt; true

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div></div> <footer class="page-edit" style="display:none;"><!----> <div class="last-updated"><span class="prefix">最后更新时间: </span> <span class="time">4/4/2020, 8:45:17 PM</span></div></footer> <!----> <!----></main> <!----> <div class="comments-wrapper" data-v-4698c43e><!----></div></div></div></div></div></div><div class="global-ui"><div class="back-to-ceiling" style="right:1rem;bottom:6rem;width:2.5rem;height:2.5rem;border-radius:.25rem;line-height:2.5rem;display:none;" data-v-a81d141e data-v-a81d141e><svg t="1574745035067" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5404" class="icon" data-v-a81d141e><path d="M526.60727968 10.90185116a27.675 27.675 0 0 0-29.21455937 0c-131.36607665 82.28402758-218.69155461 228.01873535-218.69155402 394.07834331a462.20625001 462.20625001 0 0 0 5.36959153 69.94390903c1.00431239 6.55289093-0.34802892 13.13561351-3.76865779 18.80351572-32.63518765 54.11355614-51.75690182 118.55860487-51.7569018 187.94566865a371.06718723 371.06718723 0 0 0 11.50484808 91.98906777c6.53300375 25.50556257 41.68394495 28.14064038 52.69160883 4.22606766 17.37162448-37.73630017 42.14135425-72.50938081 72.80769204-103.21549295 2.18761121 3.04276886 4.15646224 6.24463696 6.40373557 9.22774369a1871.4375 1871.4375 0 0 0 140.04691725 5.34970492 1866.36093723 1866.36093723 0 0 0 140.04691723-5.34970492c2.24727335-2.98310674 4.21612437-6.18497483 6.3937923-9.2178004 30.66633723 30.70611158 55.4360664 65.4791928 72.80769147 103.21549355 11.00766384 23.91457269 46.15860503 21.27949489 52.69160879-4.22606768a371.15156223 371.15156223 0 0 0 11.514792-91.99901164c0-69.36717486-19.13165746-133.82216804-51.75690182-187.92578088-3.42062944-5.66790279-4.76302748-12.26056868-3.76865837-18.80351632a462.20625001 462.20625001 0 0 0 5.36959269-69.943909c-0.00994388-166.08943902-87.32547796-311.81420293-218.6915546-394.09823051zM605.93803103 357.87693858a93.93749974 93.93749974 0 1 1-187.89594924 6.1e-7 93.93749974 93.93749974 0 0 1 187.89594924-6.1e-7z" p-id="5405" data-v-a81d141e></path><path d="M429.50777625 765.63860547C429.50777625 803.39355007 466.44236686 1000.39046097 512.00932183 1000.39046097c45.56695499 0 82.4922232-197.00623328 82.5015456-234.7518555 0-37.75494459-36.9345906-68.35043303-82.4922232-68.34111062-45.57627738-0.00932239-82.52019037 30.59548842-82.51086798 68.34111062z" p-id="5406" data-v-a81d141e></path></svg></div></div></div>
    <script src="/blog/assets/js/app.c6f0b635.js" defer></script><script src="/blog/assets/js/3.56d0db2f.js" defer></script><script src="/blog/assets/js/1.dc177a2a.js" defer></script><script src="/blog/assets/js/18.b7c7c6f0.js" defer></script>
  </body>
</html>
